package br.odb.bzk3.android;

import android.util.Log;
import br.odb.libscene.Actor;
import br.odb.libscene.Constants;
import br.odb.libscene.Door;
import br.odb.libscene.InvalidSectorQuery;
import br.odb.libscene.Mesh;
import br.odb.libscene.Sector;
import br.odb.libstrip.IndexedSetFace;
import br.odb.utils.math.Vec3;
import bzk3.geometry.GLES1Square;
import bzk3.geometry.GLES1Triangle;
import bzk3.geometry.GLES1TriangleFactory;
import bzk3.geometry.GLESIndexedSetFace;
import bzk3.geometry.ObjMesh;

/**
 * 
 * @author Daniel "Monty" Monteiro
 */
public class GameSector extends Sector {
	public int dist;
	public GLES1Triangle[][] decals = new GLES1Triangle[ 6 ][];
	public GLES1Square[] face;
	public Mesh meshWalls[];
	public long frame;
	public Vec3 relPos = new Vec3();
	public Vec3 relPosVol = new Vec3();
	int visibleFaces;
	public int incidingDirection;
	
	public boolean geometryLoaded = false;
	public GameSector[][] leafCache = new GameSector[ 4 ][];
	public GameSector[] cachedNeighBours = new GameSector[ 6 ];
	
	// ------------------------------------------------------------------------------------------------------------
	public GameSector(float i, float i0, float i1, float i2, float i3, float i4) {
		super(i, i0, i1, i2, i3, i4);

		visibleFaces = 0;
		face = new GLES1Square[6];
		meshWalls = new Mesh[ 6 ];
	}

	public void closeAllDoors() {
		Door door;

		for (int c = 0; c < 6; ++c) {

			door = getDoor(c);

			if (door != null) {
				Log.d( "BZK3", "closing door");
				door.close();
			}
		}

	}

	
	// ------------------------------------------------------------------------------------------------------------

	public void lit() {
		// //Android
		 float candelas = this.getEmissiveLightningIntensity();
		 for (int c = 0; c < 6; c++)
			 if (this.face[c] != null)
				 this.face[c].setColorWithOffset( getColor( c ), candelas );
		 //MIDP
//		 int color;
//		
//		 if (candelas>=255)
//		 candelas=255;
//		
//		 float _candelas=candelas;
//		 _candelas/=128.0f;
//		
//		 for (int c=0;c<6;c++)
//		 {
//		 if (iColor[c] == null)
//		 continue;
//		
//		 color=iCache[c].getVertexBuffer().getDefaultColor();
//		 color=getARGBColor((int)(iColor[c].r*_candelas),(int)(iColor[c].g*_candelas),(int)(iColor[c].b*_candelas));
//		 iCache[c].getVertexBuffer().setDefaultColor(color);
//		 }

	}

	// ------------------------------------------------------------------------------------------------------------
	public int locateEscapePlane(Vec3 vec) throws InvalidSectorQuery {

		if ((vec.getY() >= getY0() && vec.getY() <= getY1())
				&& (vec.getZ() >= getZ0() && vec.getZ() <= getZ1())) {

			if (vec.getX() >= getX1())
				return Constants.FACE_E;

			if (vec.getX() <= getX0())
				return Constants.FACE_W;

			return Constants.INSIDE;
		}

		if ((vec.getX() >= getX0() && vec.getX() <= getX1())
				&& (vec.getZ() >= getZ0() && vec.getZ() <= getZ1())) {

			if (vec.getY() >= getY1())
				return Constants.FACE_CEILING;

			if (vec.getY() <= getY0())
				return Constants.FACE_FLOOR;

			return Constants.INSIDE;
		}

		if ((vec.getY() >= getY0() && vec.getY() <= getY1())
				&& (vec.getX() >= getX0() && vec.getX() <= getX1())) {

			if (vec.getZ() >= getZ1())
				return Constants.FACE_S;

			if (vec.getZ() <= getZ0())
				return Constants.FACE_N;

			return Constants.INSIDE;
		}

		throw new InvalidSectorQuery();
	}

	@Override
	public void onSectorEnteredBy(Actor actor) {
		super.onSectorEnteredBy(actor);

		openAllDoors();
	}

	// ------------------------------------------------------------------------------------------------------------
	public void onSectorLeftBy(GameActor actor) {
		super.onSectorLeftBy(actor);
		closeAllDoors();
	}

	public void openAllDoors() {

		Door door;

		for (int c = 0; c < 6; ++c) {

			door = getDoor(c);

			if (door != null) {
				Log.d( "BZK3", "opening door");
				door.open();
			}
		}
	}

	public void reset() {
		super.setEmissiveLightningIntensity( (short) 0 );
		relPos.set( 0.0f, 0.0f, 0.0f );
//		for ( int c =0; c < 6; ++c ) {
//			if ( getDoor( c ) != null && getDoor( c ).getMesh() != null )
//				getDoor( c ).getMesh().setVisibility( false );
//		}
	}

	@Override
	public void setDoorAt(int slot, int sector) {
		doors[slot] = new GameDoor(sector, getCenter());
	}
	
	public void setDoorAt(int slot, int sector, String decalName ) {
		
		doors[slot] = new GameDoor(sector, getCenter());
		setDecalAt( slot, decalName );
	}

	// ------------------------------------------------------------------------------------------------------------
	public void setLink(int s, int i0, String token) {
		super.setLink(s, i0);

		if (i0 == NO_LINK)
			visibleFaces++;
	}

	// ------------------------------------------------------------------------------------------------------------
	@Override
	public void setLinks(int l0, int l1, int l2, int l3, int l4, int l5) {
		super.setLinks(l0, l1, l2, l3, l4, l5);
		visibleFaces = 0;
		for (int c = 0; c < 6; ++c)
			try {
				if (getLink(c) == Constants.NO_LINK)
					++visibleFaces;
			} catch (InvalidSlotException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

	}

	public void setVisible(boolean v) {

		if (visibleFaces != 0) {

			for (int c = 0; c < 6; c++) {
				if (face[c] != null) {
					face[c].setVisibility(v);
				}
			}
		}
	}

	public void setDecalAt(int face, String decalName) {
		
		String decalFilename = decalName;
		Decal decal = new Decal( decalName, decalFilename );
		doors[ face ].setMesh( applyToFace( face, decal ) );
	}

	private Mesh applyToFace(int face, Decal decal) {
		
		Decal toReturn = new Decal();
		
		for ( int c = 0; c < decal.faces.size(); ++c ) {
			toReturn.addFace( this.applyToFace( face, (GLES1Triangle) decal.faces.get( c ) ) );  //, c * 0.00125f ) );
		}
		
		return toReturn;
	}



	public GLES1Triangle applyToFace( int faceNum,	GLES1Triangle face) {
		return applyToFace( faceNum, face, 0.0f );
	}

	
	
	private GLES1Triangle applyToFace( int faceNum, GLES1Triangle face, float delta ) {
		
		GLES1Triangle toReturn = null;

		
		float x;
		float y;
		float z;
		float x0 = 0.0f;
		float y0 = 0.0f;
		float z0 = 0.0f;
		float x1 = 0.0f;
		float y1 = 0.0f;
		float z1 = 0.0f;
		float x2 = 0.0f;
		float y2 = 0.0f;
		float z2 = 0.0f;
		float dx = getDX();
		float dy = getDY();
		float dz = getDZ();
		
		x = this.getX0() + dx / 2;
		y = this.getY0();
		z = this.getZ0() + dz / 2;
		switch ( faceNum ) {
			case Sector.FACE_N: {
				x0 = x + ( face.x0 ) * dx;
				y0 = ( dy / 2.0f ) + y + ( face.y0 ) * dy;
				z0 = z - delta - ( dz / 2 );
				x1 = x + ( face.x1 ) * dx;
				y1 = ( dy / 2.0f ) + y + ( face.y1 ) * dy;
				z1 = z - delta - ( dz / 2 );
				x2 = x + ( face.x2 ) * dx;
				y2 = ( dy / 2.0f ) + y + ( face.y2 ) * dy;
				z2 = z - delta - ( dz / 2 );
			}
			break;
			case Sector.FACE_E: {
				x0 = x - delta + ( dx / 2 );
				y0 = ( dy / 2.0f ) + y + ( face.y0 * dy );
				z0 = z + ( face.x0 * dx );
				x1 = x - delta + ( dx / 2 );
				y1 = ( dy / 2.0f ) + y + ( face.y1 * dy );
				z1 = z + ( face.x1 * dz );
				x2 = x - delta + ( dx / 2 );
				y2 = ( dy / 2.0f ) + y + ( face.y2 * dy );
				z2 = z + ( face.x2 * dz );
			}
			break;
			case Sector.FACE_S: {
				x0 = x + ( face.x0 ) * dx;
				y0 = ( dy / 2.0f ) + y + ( face.y0 ) * dy;
				z0 = z + delta + ( dz / 2 );
				x1 = x + ( face.x1 ) * dx;
				y1 = ( dy / 2.0f ) + y + ( face.y1 ) * dy;
				z1 = z + delta + ( dz / 2 );
				x2 = x + ( face.x2 ) * dx;
				y2 = ( dy / 2.0f ) + y + ( face.y2 ) * dy;
				z2 = z + delta + ( dz / 2 );
			}
			break;
			case Sector.FACE_W: {
				x0 = x + delta - ( dx / 2 );
				y0 = ( dy / 2.0f ) + y + ( face.y0 * dy );
				z0 = z + ( face.x0 * dx );
				x1 = x + delta - ( dx / 2 );
				y1 = ( dy / 2.0f ) + y + ( face.y1 * dy );
				z1 = z + ( face.x1 * dz );
				x2 = x + delta - ( dx / 2 );
				y2 = ( dy / 2.0f ) + y + ( face.y2 * dy );
				z2 = z + ( face.x2 * dz );			}
			break;
			case Sector.FACE_FLOOR: {
				x0 = x + ( face.x0 ) * dx;
				y0 = y + delta ;// + ( face.z0 );
				z0 = z + ( face.y0 ) * dz;
				x1 = x + ( face.x1 ) * dx;
				y1 = y + delta ;// + ( face.z1 );
				z1 = z + ( face.y1 ) * dz;
				x2 = x + ( face.x2 ) * dx;
				y2 = y + delta ;// + ( face.z2 );
				z2 = z + ( face.y2 ) * dz;
			}
			break;
			case Sector.FACE_CEILING: {
				x0 = x + ( face.x0 );
				y0 = - delta + getDY() + y + ( face.z0 );
				z0 = z + ( face.y0 );
				x1 = x + ( face.x1 );
				y1 = - delta + getDY() + y + ( face.z1 );
				z1 = z + ( face.y1 );
				x2 = x + ( face.x2 );
				y2 = - delta + getDY() + y + ( face.z2 );
				z2 = z + ( face.y2 );
			}
			break;
		}
		long argb = face.getColor().getARGBColor();
		argb = argb & 0x00FFFFFF;
		int clipped = ( int ) argb;
		toReturn = GLES1TriangleFactory.getInstance().makeTrig(x0, y0, z0, x1, y1, z1, x2, y2, z2, clipped );
		
		return toReturn;
	}
	
	
}
